package com.copc.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.copc.common.config.Config;
import com.copc.common.model.ChangeLockStatusVo;
import com.copc.common.model.OrderEntrySchema;
import com.copc.common.model.VoucherRefundVo;
import com.copc.common.model.order.OrderVo;
import com.copc.common.model.vo.*;
import com.copc.common.util.CommonUtil;
import com.copc.copc.entity.MerchantConfig;
import com.copc.copc.entity.OrderMessage;
import com.copc.copc.pojo.vo.order.ByteMsgVO;
import com.copc.copc.pojo.vo.order.ByteVerifyMsg;
import com.copc.copc.pojo.vo.order.OrderShoppromoDetailsVO;
import com.copc.copc.service.IMerchantConfigService;
import com.copc.copc.service.IOrderMessageService;
import com.copc.service.CopcService;
import com.copc.service.IsvDouyinService;
import com.copc.common.util.OrderNoGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.util.UriComponentsBuilder.fromUri;
import static org.springframework.web.util.UriComponentsBuilder.fromUriString;

/**
 * 抖音API相关接口
 */
@Slf4j
@Service
public class IsvDouyinServiceImpl implements IsvDouyinService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private CopcService copcService;

    @Resource
    private IMerchantConfigService merchantConfigService;

    @Resource
    private IOrderMessageService orderMessageService;
    /**
     * 查询券状态地址
     */
    private static final URI ItemOrderInfoURI = UriComponentsBuilder.fromHttpUrl("https://open.douyin.com/api/apps/trade/v2/order/query_item_order_info").build().toUri();

    /**
     * 抖音退款地址
     */
    private static final URI createRefundURI = UriComponentsBuilder.fromHttpUrl("https://open.douyin.com/api/apps/trade/v2/refund/create_refund").build().toUri();

    /**
     * 同步退款审核
     */
    private static final URI merchantAuditCallbackURI = UriComponentsBuilder.fromHttpUrl("https://open.douyin.com/api/apps/trade/v2/refund/merchant_audit_callback").build().toUri();

    /**
     * 券加解锁
     */
    public static final String lockCertificatesStr = "https://open.douyin.com/api/apps/trade/v2/toolkit/change_lock_status";

    /**
     * 推动结算状态
     */
    public static final String pushServiceDone = "https://open.douyin.com/api/apps/trade/v2/toolkit/push_service_done";

    @Override
    public boolean douYinRefund(VoucherRefundVo voucherRefundVo) {

        String orderNo = voucherRefundVo.getOrderNo();
        String douyinOrderId = voucherRefundVo.getDouyinOrderId();
        String appId = voucherRefundVo.getAppId();
        String itemOrderId = voucherRefundVo.getItemOrderId();

        String outRefundNo = "RF-" + OrderNoGenerator.generateOrderNumber();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("out_order_no", orderNo);
        jsonObject.put("out_refund_no", outRefundNo);

        //界面跳转逻辑
        OrderEntrySchema orderEntrySchema = new OrderEntrySchema();
        JSONObject params = new JSONObject();
        params.put("orderNo", orderNo);
        orderEntrySchema.setPath("pages/index/index");
        orderEntrySchema.setParams(params.toString());
        jsonObject.put("order_entry_schema", orderEntrySchema);

        JSONArray item_order_array = new JSONArray();

        if (StrUtil.isBlank(itemOrderId)) {//整单退
            List<String> itemOrderIds = this.queryItemOrderInfo(douyinOrderId, appId);
            for (String id : itemOrderIds) {
                JSONObject item_order_detail = new JSONObject();
                item_order_detail.put("item_order_id", id);
                item_order_array.add(item_order_detail);
            }
        } else {//部分退
            JSONObject item_order_detail = new JSONObject();
            item_order_detail.put("item_order_id", itemOrderId);
            item_order_array.add(item_order_detail);
        }

        jsonObject.put("item_order_detail", item_order_array);

        log.info("抖音退款json:{}", jsonObject.toJSONString());

        RequestEntity<JSONObject> request = RequestEntity.post(createRefundURI)
                .header("access-token", copcService.getClientToken(appId))
                .contentType(APPLICATION_JSON).body(jsonObject);
        JSONObject response = restTemplate.exchange(request, JSONObject.class).getBody();

        log.info("douYinRefund response:{}", response);

        String subDescription = response.getJSONObject("extra").getString("sub_description");

        // 判断 sub_description 是否为 "success"
        if ("success".equals(subDescription)) {
            return this.merchantAuditCallback(outRefundNo, appId);
        }
        return false;
    }

    @Override
    public boolean unlockCertificate(ChangeLockStatusVo changeLockStatusVo) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("access-token", copcService.getClientToken(changeLockStatusVo.getAppId()));
        //copcService.getClientToken(changeLockStatusVo.getAppId())

        try {

            QueryWrapper<OrderMessage> orderMessageWrapper = new QueryWrapper();
            orderMessageWrapper.eq("order_no", changeLockStatusVo.getOrderNo());//启用的商户配置
            List<OrderMessage> lists = orderMessageService.list(orderMessageWrapper);
            log.info("orderlist orderNo : {},size :{}", changeLockStatusVo.getOrderNo(), lists.size());
            if (CommonUtil.isNotEmpty(lists) && lists.size() > 0) {
                OrderMessage orderMessage = lists.get(0);

                String createOrderMessage = orderMessage.getCreateOrderMessage();

                String voucherMessage = orderMessage.getVoucherMessage();

                //获取原核销信息
                ByteVerifyMsg byteVerifyMsg = JSON.parseObject(voucherMessage, ByteVerifyMsg.class);

                //获取原订单信息
                ByteMsgVO byteMsgVO = JSON.parseObject(createOrderMessage, ByteMsgVO.class);


                JSONObject requestBody = new JSONObject();
                JSONObject orderInfo = new JSONObject();
                orderInfo.put("order_id", byteMsgVO.getSku_list().get(0).getDiscount_info().getDeduct_info().getDeduct_order_id());

//        JSONObject timesCardLockInfo = new JSONObject();
//        timesCardLockInfo.put("lock_count", 10);
//
//        certificateInfo.put("times_card_lock_info", timesCardLockInfo);

                List<OrderShoppromoDetailsVO> couponVerifyResults = byteVerifyMsg.getCoupon_verify_results();

                JSONArray certificates = new JSONArray();
                for (OrderShoppromoDetailsVO orderShoppromoDetailsVO : couponVerifyResults) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("certificate_id", orderShoppromoDetailsVO.getCertificate_id());
                    certificates.add(jsonObject);
                }

                orderInfo.put("certificate_info_list", certificates);
                orderInfo.put("lock_key", "1704698496438");

                requestBody.put("order_info_list", new JSONObject[]{orderInfo});
                requestBody.put("operation_type", 1);

                HttpEntity<String> requestEntity = new HttpEntity<>(requestBody.toString(), headers);

                ResponseEntity<String> respons = restTemplate.exchange(lockCertificatesStr, HttpMethod.POST, requestEntity, String.class);

                log.info("unlockCertificate respons :{}", respons.getBody());
                return true;
            }
            return false;

        } catch (Exception e) {
            log.info("解锁失败");
            return false;
        }
    }

    @Override
    public boolean pushServiceDone(ChangeLockStatusVo changeLockStatusVo) {

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("access-token", copcService.getClientToken(changeLockStatusVo.getAppId()));

        try {

            QueryWrapper<OrderMessage> orderMessageWrapper = new QueryWrapper();
            orderMessageWrapper.eq("order_no", changeLockStatusVo.getOrderNo());//启用的商户配置
            List<OrderMessage> lists = orderMessageService.list(orderMessageWrapper);
            log.info("orderlist orderNo : {},size :{}", changeLockStatusVo.getOrderNo(), lists.size());

            OrderMessage orderMessage = lists.get(0);

            String createOrderMessage = orderMessage.getCreateOrderMessage();

            String voucherMessage = orderMessage.getVoucherMessage();

            //获取原核销信息
            ByteVerifyMsg byteVerifyMsg = JSON.parseObject(voucherMessage, ByteVerifyMsg.class);

            //获取原订单信息
            ByteMsgVO byteMsgVO = JSON.parseObject(createOrderMessage, ByteMsgVO.class);

            String deductOrderId = byteMsgVO.getSku_list().get(0).getDiscount_info().getDeduct_info().getDeduct_order_id();

            JSONObject requestBody = new JSONObject();
            requestBody.put("order_id", deductOrderId);

            //组装履约ids
            List<String> verifyIds = byteVerifyMsg.getCoupon_verify_results().stream()
                    .map(OrderShoppromoDetailsVO::getVerify_id)
                    .collect(Collectors.toList());

            JSONArray verifyIdList = new JSONArray(verifyIds);
            requestBody.put("verify_id_list", verifyIdList);

            HttpEntity<String> requestEntity = new HttpEntity<>(requestBody.toString(), headers);

            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> response = restTemplate.exchange(pushServiceDone, HttpMethod.POST, requestEntity, String.class);

            log.info("pushServiceDone response : {}",response.getBody());

            return true;
        } catch (Exception e) {
            log.info("推动结算状态失败");
            return false;
        }

    }

    @Override
    public OrderVo orderDetal(String orderId, String accountId) throws URISyntaxException {

        log.info("IsvDouyinServiceImpl:orderDetal:param : {},{}", orderId, accountId);

        String orderDetailUrl = Config.getInstance().getValue("orderDetailURI");

        QueryWrapper<MerchantConfig> merchantConfigWrapper = new QueryWrapper();
        merchantConfigWrapper.eq("account_id", accountId);//启用的商户配置
        MerchantConfig merchantConfig = merchantConfigService.getOne(merchantConfigWrapper);

        URI getOrderDetailUrl = new URI(merchantConfig.getAuthUrl() + orderDetailUrl);

        log.info("getOrderDetailUrl : {}", getOrderDetailUrl);

        URI uri = fromUri(getOrderDetailUrl).pathSegment("orderDetail", "{orderId}").build(orderId);

        RequestEntity<Void> request = RequestEntity.get(uri).accept(APPLICATION_JSON).build();

        ResponseEntity<OrderVo> response = restTemplate.exchange(request, OrderVo.class);

        OrderVo order = new OrderVo();

        if (response.getStatusCode() == HttpStatus.OK) {
            order = response.getBody();
            order.setErr_no(0);
            order.setAccountId(accountId);
        }

        return order;
    }

    @Override
    public MerPriceVo merchandisePrices(String code, String accountId) throws URISyntaxException {

        log.info("IsvDouyinServiceImpl:merchandisePrices:param : {},{}", code);

        String merchandisePricesUrl = Config.getInstance().getValue("merchandisePricesURI");

        QueryWrapper<MerchantConfig> merchantConfigWrapper = new QueryWrapper();
        merchantConfigWrapper.eq("account_id", accountId);//启用的商户配置
        MerchantConfig merchantConfig = merchantConfigService.getOne(merchantConfigWrapper);

        URI getMerchandisePricesUrl = new URI(merchantConfig.getAuthUrl() + merchandisePricesUrl);

        log.info("getMerchandisePricesUrl : {}", getMerchandisePricesUrl);

        URI uri = fromUri(getMerchandisePricesUrl).pathSegment("{orderId}", "prices").build(code);

        RequestEntity<Void> request = RequestEntity.get(uri).accept(APPLICATION_JSON).build();

        ResponseEntity<MerPriceVo> response = restTemplate.exchange(request, MerPriceVo.class);

        log.info("MerchandisePrices response : {}", JSON.toJSONString(response.getBody()));

        MerPriceVo merPriceVo = new MerPriceVo();

        if (response.getStatusCode() == HttpStatus.OK) {
            merPriceVo = response.getBody();
            merPriceVo.setErr_no(0);
        }

        return merPriceVo;
    }

    @Override
    public ProductsVo getOrderProduct(String orderNo, String accountId) throws URISyntaxException {

        log.info("IsvDouyinServiceImpl:getOrderProduct:param : {},{}", orderNo);

        String orderProductUrl = Config.getInstance().getValue("orderProduct");

        QueryWrapper<MerchantConfig> merchantConfigWrapper = new QueryWrapper();
        merchantConfigWrapper.eq("account_id", accountId);//启用的商户配置
        MerchantConfig merchantConfig = merchantConfigService.getOne(merchantConfigWrapper);

        URI getorderProductUrl = new URI(merchantConfig.getAuthUrl() + orderProductUrl);

        log.info("getOrderProductUrl : {}", getorderProductUrl);

        URI uri = fromUri(getorderProductUrl).pathSegment("{orderNo}", "product").build(orderNo);

        // 创建一个 ParameterizedTypeReference 以处理泛型响应
        ParameterizedTypeReference<List<ProductVo>> responseType = new ParameterizedTypeReference<List<ProductVo>>() {
        };

        // 使用 exchange 方法来发送请求，指定 HttpMethod 为 GET 或其他 HTTP 方法
        ResponseEntity<List<ProductVo>> response = restTemplate.exchange(uri, HttpMethod.GET, null, responseType);

        log.info("OrderProduct response : {}", JSON.toJSONString(response.getBody()));


        ProductsVo productsVo = new ProductsVo();

        if (response.getStatusCode() == HttpStatus.OK) {
            productsVo.setProducts(response.getBody());
            productsVo.setErr_no(0);
        }

        return productsVo;
    }

    @Override
    public ExpressRouteVo getOrderExpress(String orderNo, String accountId) throws URISyntaxException {

        log.info("IsvDouyinServiceImpl:getOrderExpress:param : {},{}", orderNo, accountId);

        String orderExpress = Config.getInstance().getValue("orderExpress");

        QueryWrapper<MerchantConfig> merchantConfigWrapper = new QueryWrapper();
        merchantConfigWrapper.eq("account_id", accountId);//启用的商户配置
        MerchantConfig merchantConfig = merchantConfigService.getOne(merchantConfigWrapper);

        URI getOrderExpressUrl = new URI(merchantConfig.getAuthUrl() + orderExpress);

        log.info("getOrderExpress : {}", getOrderExpressUrl);

        URI uri = fromUri(getOrderExpressUrl).pathSegment("{orderNo}", "express").build(orderNo);

        ParameterizedTypeReference<List<ExpressVo>> responseType = new ParameterizedTypeReference<List<ExpressVo>>() {
        };

        // 使用 exchange 方法来发送请求，指定 HttpMethod 为 GET 或其他 HTTP 方法
        ResponseEntity<List<ExpressVo>> response = restTemplate.exchange(uri, HttpMethod.GET, null, responseType);

        log.info("OrderExpress response : {}", JSON.toJSONString(response.getBody()));


        ExpressRouteVo expressRouteVo = new ExpressRouteVo();

        if (response.getStatusCode() == HttpStatus.OK) {
            expressRouteVo.setExpressRoute(response.getBody());
            expressRouteVo.setErr_no(0);
        }

        return expressRouteVo;
    }

    @Override
    public OdrPictures getProductPictures(String productId, String accountId) throws URISyntaxException {

        log.info("IsvDouyinServiceImpl:getProductPictures:param : {},{}", productId, accountId);

        String productPictures = Config.getInstance().getValue("productPictures");

        QueryWrapper<MerchantConfig> merchantConfigWrapper = new QueryWrapper();
        merchantConfigWrapper.eq("account_id", accountId);//启用的商户配置
        MerchantConfig merchantConfig = merchantConfigService.getOne(merchantConfigWrapper);

        URI getProductPicturesUrl = new URI(merchantConfig.getAuthUrl() + productPictures);

        log.info("getProductPictures : {}", getProductPicturesUrl);

        URI uri = fromUri(getProductPicturesUrl).pathSegment("{productId}", "pictures").build(productId);

        ParameterizedTypeReference<List<Pictures>> responseType = new ParameterizedTypeReference<List<Pictures>>() {
        };

        // 使用 exchange 方法来发送请求，指定 HttpMethod 为 GET 或其他 HTTP 方法
        ResponseEntity<List<Pictures>> response = restTemplate.exchange(uri, HttpMethod.GET, null, responseType);

        log.info("productPictures response : {}", JSON.toJSONString(response.getBody()));

        OdrPictures odrPictures = new OdrPictures();

        if (response.getStatusCode() == HttpStatus.OK) {
            odrPictures.setOdrPictures(response.getBody());
            odrPictures.setErr_no(0);
        }

        return odrPictures;
    }


    @Override
    public Routes getTracking(String expressNo, String accountId) throws URISyntaxException {

        log.info("IsvDouyinServiceImpl:getTracking:param : {},{}", expressNo, accountId);

        String tracking = Config.getInstance().getValue("trackingurl");

        QueryWrapper<MerchantConfig> merchantConfigWrapper = new QueryWrapper();
        merchantConfigWrapper.eq("account_id", accountId);//启用的商户配置
        MerchantConfig merchantConfig = merchantConfigService.getOne(merchantConfigWrapper);

        URI gettrackingUrl = new URI(merchantConfig.getAuthUrl() + tracking);

        log.info("gettrackingUrl : {}", gettrackingUrl);

        URI uri = fromUri(gettrackingUrl).pathSegment("{expressNo}", "tracking").build(expressNo);

        ParameterizedTypeReference<List<Route>> responseType = new ParameterizedTypeReference<List<Route>>() {
        };

        // 使用 exchange 方法来发送请求，指定 HttpMethod 为 GET 或其他 HTTP 方法
        ResponseEntity<List<Route>> response = restTemplate.exchange(uri, HttpMethod.GET, null, responseType);

        log.info("getTracking response : {}", JSON.toJSONString(response.getBody()));

        Routes routes = new Routes();

        if (response.getStatusCode() == HttpStatus.OK) {
            routes.setRoutes(response.getBody());
            routes.setErr_no(0);
        }

        return routes;
    }

    /**
     * 查询券状态
     */
    public List queryItemOrderInfo(String orderId, String appid) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("order_id", orderId);

        log.info("抖音查询券状态 json:{}", jsonObject.toJSONString());
        RequestEntity<JSONObject> request = RequestEntity.post(ItemOrderInfoURI)
                .header("access-token", copcService.getClientToken(appid))
                .contentType(APPLICATION_JSON).body(jsonObject);
        JSONObject response = restTemplate.exchange(request, JSONObject.class).getBody();

        log.info("抖音查询券状态 response:{}", JSON.toJSONString(response));

        JSONArray itemList = response.getJSONObject("data").getJSONArray("item_list");

        // 取出 item_order_id 字段的值
        List<String> orderIds = new ArrayList<>();
        for (int i = 0; i < itemList.size(); i++) {
            JSONObject item = itemList.getJSONObject(i);
            orderIds.add(item.getString("item_order_id"));
        }
        return orderIds;
    }


    /**
     * 同步退款审核结果
     */
    public boolean merchantAuditCallback(String outRefundNo, String appid) {
        log.info("同步退款审核结果：{}", outRefundNo);

        Map<String, Object> params = new LinkedHashMap<>();

        params.put("out_refund_no", outRefundNo);
        params.put("refund_audit_status", 1);

        RequestEntity<Map<String, Object>> request = RequestEntity.post(merchantAuditCallbackURI)
                .header("access-token", copcService.getClientToken(appid))
                .contentType(MediaType.APPLICATION_JSON)
                .body(params);
        JSONObject response = restTemplate.exchange(request, JSONObject.class).getBody();

        log.info("同步退款结果 response:{}", JSON.toJSONString(response));

        JSONObject data = response.getJSONObject("data");
        if (data.getString("error_code").equals("0")) {
            return true;
        }
        return false;
    }
}
